package com.yf.exam.gpt.dashscope;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationOutput;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.aigc.generation.models.QwenParam;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.MessageManager;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.utils.Constants;
import com.yf.exam.gpt.dashscope.constant.DashScope;
import com.yf.exam.gpt.dashscope.enums.RoleEnum;
import com.yf.exam.score.bean.ScoreGptAnswer;
import com.yf.exam.score.bean.ScoreGptRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import static com.yf.exam.gpt.dashscope.DashScopeUtils.*;

/**
 * @author 1763113879@qq.com
 * @version V2.1
 * @since 2.1.0 2024/1/4 16:39
 */
@Slf4j
@Service
public class GptDashScopeService {

    /**
     * 通用AI模型调用
     * @param apiKey
     * @param queryMessage
     * @return
     */
    private GenerationOutput query(String apiKey,RoleEnum role,String queryMessage) {
        // 设置APIKEY
        Constants.apiKey = apiKey;
        // 执行
        try {
            Generation gen = new Generation();
            MessageManager msgManager = new MessageManager(10);
            Message systemMsg
                    = Message.builder().role(Role.SYSTEM.getValue()).content(role.getRoleDescription()).build();
            Message userMsg = Message.builder().role(Role.USER.getValue()).content(queryMessage).build();
            msgManager.add(systemMsg);
            msgManager.add(userMsg);
            return execModelMessage(msgManager, gen, Generation.Models.QWEN_PLUS);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            GenerationOutput output = new GenerationOutput();
            output.setText("AI模型调用异常！");
            return output;
        }
    }

    /**
     * 执行所有模型
     * @param gen
     * @param msgManager
     */
    private void foreachAllModel(Generation gen, MessageManager msgManager){
        String[] models = DashScope.ALL_MODELS;
        for (int i = 0; i<models.length; i++) {
            String model = models[i];
            String message = execModelMessage(msgManager, gen,model).getText();
            log.info("第【{}】个模型 {}- 的回答为 {}",i+1,model,message);
            log.info("========================================================");
        }
    }

    /**
     * 执行模型
     * @param msgManager
     * @param gen
     * @param model
     * @return
     */
    private GenerationOutput execModelMessage(MessageManager msgManager, Generation gen,String model){
        // 模型输出
        GenerationOutput output = null;
        // 模型执行
        try {
            QwenParam param = QwenParam.builder()
                    .model(model)
                    .messages(
                            msgManager.get())
                    .resultFormat(QwenParam.ResultFormat.MESSAGE).build();
            // 执行模型
            GenerationResult result = gen.call(param);
            // 获取模型输出
            output = result.getOutput();
            log.info("模型 {}- 的回答为 {}",model, output.getChoices().get(0).getMessage());

            return output;
        } catch (ApiException e) {
            output.setText(e.getMessage());
            e.printStackTrace();
        } catch (NoApiKeyException e) {
            output.setText(e.getMessage());
            e.printStackTrace();
        } catch (InputRequiredException e) {
            output.setText(e.getMessage());
            e.printStackTrace();
        }
        return output;
    }

    public ScoreGptAnswer queryGptScore(String apiKey, ScoreGptRequest gptRequest) {

        GenerationOutput output = query(apiKey, RoleEnum.TEACHER, getGptQuest(gptRequest));
        if (output == null) {
            return null;
        }

        String content = output.getChoices().get(0).getMessage().getContent();

        return ScoreGptAnswer.builder()
                .answerScore(getScoreByContent(content))
                .answerExplain(getDescribeByContent(content))
                .build();
    }
}
